use mongodb::{ Client, Database, bson::{ Bson, oid::ObjectId } };
use axum::Json;
use serde_json::Value;
use serde::{Serialize, Deserialize};
use dotenv::dotenv;
use std::env;
use crate::query;

use super::code;

pub mod gridfs;
pub mod gridfs_bucket;
pub mod gridfs_file;
pub mod collection;
pub mod gridfs_manage;

#[derive(Debug, Serialize, Deserialize)]
pub struct Id {
    oid: ObjectId
}

pub async fn client() -> Result<Client, Json<Value>>{
    let env_url = env::var("MONGODB_URL").unwrap_or_default();
    let url = if env_url.is_empty() { config::MONGODB_URL } else { &env_url };

    match Client::with_uri_str(url).await {
        Ok(f)=> Ok(f),
        Err(e) => Err(code::sys_("MongoDB 数据库连接错误：".to_string() + &e.to_string()))
    }
}
pub async fn connect() -> Result<Database, Json<Value>> {
    dotenv().ok();
    let env_dbname = env::var("DATABASE").unwrap_or_default();
    let dbname = if env_dbname.is_empty() { config::DATABASE } else { &env_dbname };
    let client = client().await?;
    Ok(client.database(&dbname))
}
pub async fn client_url(url:&str) -> Result<Client, Json<Value>>{
    match Client::with_uri_str(url).await {
        Ok(f)=> Ok(f),
        Err(e) => Err(code::sys_("MongoDB 数据库连接错误：".to_string() + &e.to_string()))
    }
}
pub async fn connect_db(url:&str, database:&str) -> Result<Database, Json<Value>> {
    let client = client_url(url).await?;
    Ok(client.database(&database))
}
pub async fn connect_db_(param:&Value) -> Result<Database, Json<Value>> {
    let url = query::str(&param, "url")?;
    let db = query::str(&param, "db")?;
    let client = client_url(&url).await?;
    Ok(client.database(&db))
}
// 创建一个 OjbectId
pub fn create_object_id() -> Bson {
    let x = ObjectId::new();
    let id: Bson = Bson::ObjectId( x ); // x = ObjectId::default()
    id
}
// 创建一个 OjbectId String
pub fn create_object_id_str() -> String {
    let id = create_object_id();
    get_object_id_str(&id)
}
// 获取 ObjectId 的值
pub fn get_object_id_str(id:&Bson) -> String {
    let v = serde_json::to_value(&id).unwrap();
    v.get("$oid").unwrap().as_str().unwrap().to_string()
}
// 将字符串转为 ObjectId
pub fn to_object_id<T:Into<String>>(id:T) -> Bson {
    match ObjectId::parse_str(id.into()) {
        Ok(f) => Bson::ObjectId(f),
        Err(_e) => Bson::Null
    }
}
// pub fn 